package me.hl.concurrent;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Stack;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * author: planck
 * createTime: 2016/11/25.
 */
public class ReentrantLockTest {

    private Lock lock = new ReentrantLock();
    private Condition producerCondition = lock.newCondition();
    private Condition aCondition = lock.newCondition();
    private Condition bCondition = lock.newCondition();
    private Condition cCondition = lock.newCondition();
    private static final Logger logger = LoggerFactory.getLogger(ReentrantLockTest.class);
    private final Stack<Integer> stack = new Stack();
    private Integer position = 0;

    @Test
    public void test() throws Exception {
        Thread consumer = new Thread(() -> {
            lock.lock();
            try {
                for (int i = 1; i < 10; i++) {


                    logger.info("消费第{}次", i);
                    while (stack.isEmpty()) {
                        Thread.sleep(3000);
                        logger.info("没数据 等待");
                        producerCondition.await();
                    }
                    logger.info("开始第{}次消费", i);
                    while (!stack.isEmpty()) {
                        stack.pop();
                        //logger.info("获得数据  {}", stack.pop());
                    }
                    producerCondition.signalAll();
                }
            } catch (Exception e) {
                logger.error("", e);
            } finally {
                lock.unlock();
            }
        });


        Thread producer = new Thread(() -> {
            lock.lock();
            try {
                for (int i = 1; i <= 10; i++) {
                    logger.info("制造第{}次", i);
                    while (!stack.isEmpty()) {
                        Thread.sleep(3000);
                        logger.info("栈不空啊。。等等再制造");
                        producerCondition.await();
                    }
                    logger.info("开始第{}次制造", i);
                    for (int j = 0; j < 10; j++) {
                        stack.push(j);
                    }
                    producerCondition.signalAll();
                }
            } catch (Exception e) {
                logger.error("", e);
            } finally {
                lock.unlock();
            }
        });
        consumer.start(); //不能用run 不能用run 不能用run
        producer.start();


        Thread.sleep(100000);


    }


    @Test
    public void abc() throws Exception {
        Thread a = new Thread(() -> {
            lock.lock();
            try {
                for (int i = 0; i < 10; i++) {
                    while (position == 2 || position == 3) {
                        aCondition.await();
                    }
                    logger.info("a");
                    position = 2;
                    bCondition.signalAll();
                }
            } catch (Exception e) {
                logger.error("", e);
            } finally {
                lock.unlock();
            }
        });

        Thread b = new Thread(() -> {
            lock.lock();
            try {
                for (int i = 0; i < 10; i++) {
                    while (position == 1 || position == 3) {
                        bCondition.await();
                    }
                    logger.info("b");
                    position = 3;
                    cCondition.signalAll();
                }
            } catch (Exception e) {
                logger.error("", e);
            } finally {
                lock.unlock();
            }
        });

        Thread c = new Thread(() -> {
            lock.lock();
            try {
                for (int i = 0; i < 10; i++) {
                    while (position == 1 || position == 2) {
                        cCondition.await();
                    }
                    logger.info("c");
                    position = 1;
                    aCondition.signalAll();
                }
            } catch (Exception e) {
                logger.error("", e);
            } finally {
                lock.unlock();
            }
        });


        position = 1;

        c.start();
        b.start();
        a.start();


        Thread.sleep(10000);


    }
}
